package com.powernode.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.domain.Prod;
import com.powernode.domain.ProdTagReference;
import com.powernode.domain.Sku;
import com.powernode.mapper.ProdMapper;
import com.powernode.mapper.SkuMapper;
import com.powernode.model.ChangeStock;
import com.powernode.model.ProdChange;
import com.powernode.model.SkuChange;
import com.powernode.service.ProdService;
import com.powernode.service.ProdTagReferenceService;
import com.powernode.service.SkuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 贺
* @description 针对表【prod(商品)】的数据库操作Service实现
* @createDate 2024-07-18 13:24:14
*/
@Service
public class ProdServiceImpl extends ServiceImpl<ProdMapper, Prod>
    implements ProdService{

    @Resource
    private ProdMapper prodMapper;
    @Resource
    private ProdTagReferenceService prodTagReferenceService;
    @Resource
    private SkuService skuService;
    @Resource
    private SkuMapper skuMapper;

    /**
     * 新增商品
     *
     * @param prod
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveProd(Prod prod) {
        // 1. 新增商品
        // 补充商品对象属性
        prod.setShopId(1L);
        prod.setSoldNum(0);
        prod.setCreateTime(new Date());
        prod.setUpdateTime(new Date());
        prod.setPutawayTime(new Date());
        prod.setVersion(0);
        Prod.DeliveryModeVo deliveryModeVo = prod.getDeliveryModeVo();
        prod.setDeliveryMode(JSONObject.toJSONString(deliveryModeVo));

        int i = prodMapper.insert(prod);

        if (i > 0) {
            // 2. 处理商品与分组标签的关系
            // 获取商品ID
            Long prodId = prod.getProdId();
            // 获取商品分组标签集合
            List<Long> tagIdList = prod.getTagList();
            // 判断集合是否为空
            if (CollectionUtil.isNotEmpty(tagIdList) && tagIdList.size() > 0) {
                // 创建商品与分组标签的关系集合
                List<ProdTagReference> prodTagReferenceList = CollectionUtil.newArrayList();
                // 遍历商品分组标签集合
                tagIdList.forEach(tagId -> {
                    // 每次循环，创建商品与分组标签的关系对象
                    ProdTagReference prodTagReference = new ProdTagReference();
                    prodTagReference.setProdId(prodId);
                    prodTagReference.setTagId(tagId);
                    prodTagReference.setShopId(1L);
                    prodTagReference.setStatus(1);
                    prodTagReference.setCreateTime(new Date());
                    prodTagReferenceList.add(prodTagReference);
                });
                // 批量添加商品与分组标签的关系
                prodTagReferenceService.saveBatch(prodTagReferenceList);
            }

            // 3. 处理商品与商品SKU的关系
            // 获取商品sku集合
            List<Sku> skuList = prod.getSkuList();
            // 判断商品sku集合是否为空
            if (CollectionUtil.isNotEmpty(skuList) && skuList.size() > 0) {
                // 遍历商品sku集合
                skuList.forEach(sku -> {
                    // 补充商品sku对象属性
                    sku.setProdId(prodId);
                    sku.setCreateTime(new Date());
                    sku.setUpdateTime(new Date());
                    sku.setVersion(0);
                    sku.setActualStocks(sku.getStocks());
                    sku.setStatus(1);
                });
                // 批量添加商品sku
                skuService.saveBatch(skuList);
            }
        }
        return i > 0;
    }

    /**
     * 根据商品ID查询商品详情
     *
     * @param prodId
     * @return
     */
    @Override
    public Prod queryProdById(Long prodId) {
        // 1. 查询商品详情
        Prod prod = prodMapper.selectById(prodId);
        if (ObjectUtil.isNotNull(prod)) {
            // 2. 查询商品分组标签集合
            List<ProdTagReference> prodTagReferenceList = prodTagReferenceService.list(new LambdaQueryWrapper<ProdTagReference>()
                    .eq(ProdTagReference::getProdId, prodId));
            // 判断商品分组标签集合是否为空
            if (CollectionUtil.isNotEmpty(prodTagReferenceList) && prodTagReferenceList.size() > 0) {
                // 获取商品分组标签ID集合
                List<Long> tagIdList = prodTagReferenceList.stream().map(ProdTagReference::getTagId).collect(Collectors.toList());
                prod.setTagList(tagIdList);
            }

            // 3. 查询商品sku
            List<Sku> skuList = skuService.list(new LambdaQueryWrapper<Sku>()
                    .eq(Sku::getProdId, prodId));
            if (CollectionUtil.isNotEmpty(skuList) && skuList.size() > 0) {
                prod.setSkuList(skuList);
            }
        }
        return prod;
    }

    /**
     * 修改商品
     *
     * @param prod
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean modifyProd(Prod prod) {
        // 1. 修改商品
        // 补充商品对象属性
        prod.setUpdateTime(new Date());
        int i = prodMapper.updateById(prod);
        // 获取商品ID
        Long prodId = prod.getProdId();
        if (i > 0) {
            // 2. 修改商品与分组标签的关系
            // 商品对象中的tagList集合中的元素只是商品和分组标签关系对象的ID，先根据商品ID删除原有的商品和分组标签关系
            prodTagReferenceService.remove(new LambdaQueryWrapper<ProdTagReference>()
                    .eq(ProdTagReference::getProdId, prodId));

            // 获取商品对象中的tagList集合
            List<Long> tagList = prod.getTagList();
            if (CollectionUtil.isNotEmpty(tagList) && tagList.size() > 0) {
                // 创建商品与分组标签的关系集合
                List<ProdTagReference> prodTagReferenceList = CollectionUtil.newArrayList();
                // 遍历商品分组标签集合
                tagList.forEach(tagId -> {
                    // 每次遍历，创建商品与分组标签的关系对象
                    ProdTagReference prodTagReference = new ProdTagReference();
                    prodTagReference.setProdId(prodId);
                    prodTagReference.setTagId(tagId);
                    prodTagReference.setShopId(1L);
                    prodTagReference.setStatus(1);
                    prodTagReference.setCreateTime(new Date());
                    prodTagReferenceList.add(prodTagReference);
                });
                // 批量添加商品与分组标签的关系
                prodTagReferenceService.saveBatch(prodTagReferenceList);
            }

            // 3. 修改商品与商品SKU的关系
            // 如果修改商品时新增了商品属性，则需要先删除原有的商品sku，然后再添加新的商品sku
            // 删除原有的商品sku
            skuService.remove(new LambdaQueryWrapper<Sku>()
                    .eq(Sku::getProdId, prodId));

            // 从商品对象中获取skuList集合，集合中的sku对象携带了商品ID
            List<Sku> skuList = prod.getSkuList();
            // 判断skuList集合是否为空
            if (CollectionUtil.isNotEmpty(skuList) && skuList.size() > 0) {
                // 遍历skuList集合
                skuList.forEach(sku -> {
                    // 补充商品sku对象属性
                    sku.setProdId(prodId);
                    sku.setUpdateTime(new Date());
                    sku.setActualStocks(sku.getStocks());
                    sku.setCreateTime(new Date());
                    sku.setVersion(0);
                });
                // 批量添加商品sku
                skuService.saveBatch(skuList);
            }
        }
        return i > 0;
    }

    /**
     * 批量删除商品
     *
     * @param prodIds
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeProdByIds(List<Long> prodIds) {
        // 1. 删除商品和分组标签的关系
        boolean flag = prodTagReferenceService.remove(new LambdaQueryWrapper<ProdTagReference>()
                .in(ProdTagReference::getProdId, prodIds));
        if (flag) {
            // 2. 商户商品sku
            skuService.remove(new LambdaQueryWrapper<Sku>()
                    .in(Sku::getProdId, prodIds));
            // 3. 删除商品
            prodMapper.deleteBatchIds(prodIds);
        }
        return flag;
    }

    /**
     * 根据商品ID查询商品详情
     *
     * @param prodId
     * @return
     */
    @Override
    public Prod queryWxProdInfoById(Long prodId) {
        // 1. 查询商品详情
        Prod prod = prodMapper.selectById(prodId);
        // 2. 根据商品id查询商品sku
        List<Sku> skuList = skuService.list(new LambdaQueryWrapper<Sku>()
                .eq(Sku::getProdId, prodId));
        prod.setSkuList(skuList);
        return prod;
    }

    /**
     * 修改商品prod和sku库存
     *
     * @param changeStock
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changeProdAndSkuStock(ChangeStock changeStock) {

        Boolean flag = false;

        // 获取商品sku购买数量对象
        List<SkuChange> skuChangeList = changeStock.getSkuChangeList();

        // MyBatis-Plus 提供了乐观锁插件 OptimisticLockerInterceptor 用于处理乐观锁，但是对于批量更新操作，乐观锁插件默认不会生效。要实现批量更新时的乐观锁控制，需要自定义批量更新的逻辑
        // Variable used in lambda expression should be final or effectively final
        /*skuChangeList.forEach(skuChange -> {
            Long skuId = skuChange.getSkuId();
            Sku sku = skuService.getById(skuId);
            Integer count = skuMapper.updateSkuStock(skuId, skuChange.getCount(), sku.getVersion());
            if (1 == count) {
                flag = true;
            } else {
                throw new RuntimeException("商品sku库存更新失败，skuId：" + skuId);
            }
        });*/
        // 使用普通for循环
        for (SkuChange skuChange : skuChangeList) {
            Long skuId = skuChange.getSkuId();
            Sku sku = skuService.getById(skuId);
            Integer count = skuMapper.updateSkuStock(skuId, skuChange.getCount(), sku.getVersion());
            if (1 == count) {
                flag = true;
            } else {
                throw new RuntimeException("商品sku库存更新失败，skuId：" +skuId);
            }
        }

        // 获取商品prod购买数量对象
        List<ProdChange> prodChangeList = changeStock.getProdChangeList();
        for (ProdChange prodChange : prodChangeList) {
            Long prodId = prodChange.getProdId();
            Prod prod = prodMapper.selectById(prodId);
            Integer count = prodMapper.updateProdStock(prodId, prodChange.getCount(), prod.getVersion());
            if (1 == count) {
                flag = true;
            } else {
                throw new RuntimeException("商品prod库存更新失败，prodId：" + prodId);
            }
        }

        return flag;
    }
}




